package com.yohann.designPattern.prototype.deepClone;

import java.io.*;

/**
 * <p>
 * 深拷贝原型
 * </p>
 *
 * @author Yohann
 * @since 2021/2/2 15:52
 */
public class DeepPrototype implements Serializable, Cloneable {
    private static final Long serialVersionUID = 1L;

    String name;
    DeepCloneableTarget target;

    /**
     * 对引用数据类型进行单独处理
     */
    @Override
    protected DeepPrototype clone() throws CloneNotSupportedException {
        DeepPrototype deep = (DeepPrototype) super.clone();

        deep.target = (deep.target.clone());

        return deep;
    }

    /**
     * 通过序列化进行深拷贝
     */
    public DeepPrototype deepClone() {
        ByteArrayOutputStream byteArrayOutputStream = null;
        ObjectOutputStream objectOutputStream = null;
        ByteArrayInputStream byteArrayInputStream = null;
        ObjectInputStream objectInputStream = null;

        try {
            //序列化
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);

            //当前对象以对象流输出
            objectOutputStream.writeObject(this);

            //反序列
            byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            objectInputStream = new ObjectInputStream(byteArrayInputStream);

            //转成对象
            return (DeepPrototype) objectInputStream.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                if (objectInputStream != null) {
                    objectInputStream.close();
                }
                if (byteArrayInputStream != null) {
                    byteArrayInputStream.close();
                }
                if (objectOutputStream != null) {
                    objectOutputStream.close();
                }
                if (byteArrayOutputStream != null) {
                    byteArrayOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}